#ifndef BE_GRAPHICS_SYSTEM_H_INCLUDED
#define BE_GRAPHICS_SYSTEM_H_INCLUDED

#include "be_framebuffer.h"
#include "be_vertex_array.h"
#include "be_texture.h"
#include "be_shader.h"
#include "be_mesh.h"
#include "be_light.h"
#include "be_material.h"
#include "be_buffer.h"
#include "be_camera.h"

#include "src/math/vector3f.h"
#include "src/math/vector4f.h"

class BeGraphicsSystem
{
public:
	BeGraphicsSystem();
	void clear(const GLenum mask);
	void enable(const GLenum cap);
	void disable(const GLenum cap);
	void hint(const GLenum target, const GLenum hint);
	void shadeModel(const GLenum mode);
	void cullFace(const GLenum mode);
	void bindFramebuffer(BeFramebuffer* const framebuffer);
	void bindVertexArray(BeVertexArray* const vertexArray);
	void bindTexture2D(BeTexture2D* const texture);
	void useProgram(BeProgram* const program);
	void drawMesh(const BeMesh* const mesh);

	void matrixPush(const GLenum matrixMode);
	void matrixPop(const GLenum matrixMode);
	void matrixLoad(const GLenum matrixMode, const float* const m);
	void matrixLoadIdentity(const GLenum matrixMode);
	void matrixOrtho(const GLenum matrixMode, const double l, const double r, const double b, const double t, const double n, const double f);
	void matrixTranslate(const GLenum matrixMode, const float x, const float y, const float z);
	void matrixRotate(const GLenum matrixMode, const GLfloat angle, const float x, const float y, const float z);
	void matrixScale(const GLenum matrixMode, const float x, const float y, const float z);
	void matrixMult(const GLenum matrixMode, const float* const m);

	void matrixFrustum(const GLenum matrixMode, const double l, const double r, const double b, const double t, const double n, const double f);
	void matrixPerspective(const GLenum matrixMode, const float fovy, const float aspect, const float zNear, const float zFar);

	void lightModel(const GLenum pname, const Vector4f& params);
	void lightModel(const GLenum pname, const GLenum param);

	void light(const GLenum lightId, const GLenum pname, const GLfloat* const params);

	void material(const GLenum face, const GLenum pname, const Vector4f& params);
	void material(const GLenum face, const GLenum pname, const float param);

	void applyCamera(const BeCameraPerspective& camera);

	void applyLight(const GLenum lightId, const BeLight* const l);
	void applyMaterial(const GLenum face, const BeMaterial* const m);

	void bindBuffer(const GLenum target, BeBuffer* const buffer);

private:
	BeGraphicsKernel m_graphicsKernel;
};

#endif
